from typing import List
from dataclasses import dataclass, field
from .common_meta_info import CommonTableMetaInfo, CommonColumnMetaInfo, create_common_meta_info
from .sql_table_info import TableInfoSQL, TableInfoConfig
from datetime import datetime

# SQL 类型到 Java 类型的映射函数
def map_sql_to_java_type(sql_type: str) -> str:
    # 将 SQL 类型转为大写，以便统一处理
    sql_type_upper = sql_type.upper()

# SQL 类型到 Java 类型的映射函数
def map_sql_to_java_type(sql_type: str) -> str:
    # 将 SQL 类型转为大写，以便统一处理
    sql_type_upper = sql_type.upper()

    # 按前缀长度排序的类型映射规则
    type_prefix_mapping = {
        'MEDIUMINT': 'Integer',
        'TIMESTAMP': 'LocalDateTime',  # 长前缀，确保优先匹配
        'DATETIME': 'LocalDateTime',
        'DATE': 'LocalDate',  # 区分 DATE 和 DATETIME
        'TIME': 'LocalTime',
        'SMALLINT': 'Integer',
        'TINYINT': 'Integer',
        'BIGINT': 'Long',
        'DECIMAL': 'BigDecimal',
        'INTEGER': 'Integer',
        'BOOLEAN': 'Boolean',  # 优先匹配 BOOLEAN，避免被 BIT 覆盖
        'VARCHAR': 'String',
        'CHAR': 'String',
        'DOUBLE': 'Double',
        'FLOAT': 'Float',
        'BIT': 'Boolean',
        'INT': 'Integer',  # 短前缀，需放在最后避免覆盖
        'TEXT': 'String',
        'BLOB': 'byte[]',   # 二进制数据
        'REAL': 'Double',   # 兼容 SQLite 中的 REAL 类型
        'NUMERIC': 'BigDecimal',  # 高精度数字类型
        'ENUM': 'String',   # 枚举类型映射为 String
        'SET': 'String',    # 集合类型映射为 String
        # 可以添加更多映射规则...
    }

    # 遍历类型前缀映射规则，找到匹配的前缀
    for prefix, java_type in type_prefix_mapping.items():
        if sql_type_upper.startswith(prefix):
            return java_type

    # 默认返回 Object
    return 'Object'

# 用于生成 SpringBoot 代码的列元信息
@dataclass
class SpringBootColumnMetaInfo(CommonColumnMetaInfo):
    java_type_name: str = field(init=False)  # 将 java_type_name 作为类变量，并在初始化时设置

    def __post_init__(self):
        # 初始化时根据 SQL 类型设置 Java 类型
        self.java_type_name = map_sql_to_java_type(self.sql_raw_info.type)

    # 默认返回 Object
    def __str__(self) -> str:
        # 自定义字符串表示，包含 SQL 原始信息和 Java 类型信息
        return (
            f"SpringBootColumnMetaInfo: "
            f"字段名 (SQL): {self.sql_raw_info.name} ｜ "
            f"字段类型 (SQL): {self.sql_raw_info.type} ｜ "
            f"Java 类型: {self.java_type_name} ｜ "
            f"字段中文名: {self.config.chinese_name} ｜ "
            f"是否显示: {'显示' if self.config.column_show else '隐藏'}"
        )

# 用于生成 SpringBoot 代码的表元信息
@dataclass
class SpringBootTableMetaInfo(CommonTableMetaInfo):
    java_package_name: str
    columns: List[SpringBootColumnMetaInfo]

    # 在初始化时将 CommonColumnMetaInfo 转换为 SpringBootColumnMetaInfo
    def __post_init__(self):
        # 转换列信息
        self.columns = [
            SpringBootColumnMetaInfo(
                sql_raw_info=column.sql_raw_info,
                config=column.config,
            )
            for column in self.columns
        ]

    def __str__(self) -> str:
        columns_str = "\n".join([str(column) for column in self.columns])
        return (
            f"Table: {self.sql_raw_info.table_name}\n"
            f"  Class Name: {self.class_name}\n"
            f"  Package Name: {self.java_package_name}\n"
            f"  Display Name: {self.chinese_name}\n"
            f"  Current Date: {self.current_date}\n"  # 继承自父类的字段
            f"  Version: {self.version}\n"  # 继承自父类的字段
            f"  Columns:\n{columns_str}"
        )


# 根据 TableInfoSQL 生成 SpringBootTableMetaInfo 实例的函数
def create_springboot_meta_info(table_info_sql: TableInfoSQL, config: TableInfoConfig) -> SpringBootTableMetaInfo:
    # 生成 CommonTableMetaInfo 实例，传递 current_date 和 version
    common_meta_info = create_common_meta_info(table_info_sql, config)

    # 创建 SpringBootTableMetaInfo 实例
    springboot_table_meta_info = SpringBootTableMetaInfo(
        sql_raw_info=common_meta_info.sql_raw_info,
        chinese_name=common_meta_info.chinese_name,
        columns=common_meta_info.columns,  # columns 在 __post_init__ 中会转换为 SpringBootColumnMetaInfo
        java_package_name=config.java_package_name,
        current_date=common_meta_info.current_date,  # 将 current_date 传递给 SpringBootTableMetaInfo
        version=common_meta_info.version,  # 将 version 传递给 SpringBootTableMetaInfo

        class_name=common_meta_info.class_name,
        table_name=common_meta_info.table_name,
        entity_name=common_meta_info.entity_name
    )

    return springboot_table_meta_info